<!-- 7865 -->

<template>
  <div style="height: calc(100vh - 100px)">
    <div class="talkContainer">
      <div class="talkContent" ref="chatContent">
        <div class="all">
          <div class="icon">
            <img src="@/assets/images/talk.png" alt="" />
          </div>
          <div class="aitalk" v-html="aitalk"></div>
        </div>
        <div class="talkQA" v-for="item in talkList" :key="item.id">
          <div v-if="item.person == 'mine'" class="mine">
            <img
              style="width: 100px; height: 100px"
              v-if="item.img"
              :src="item.img"
              alt=""
            />
            <div class="question">
              {{ item.say }}
            </div>
            <div class="icon">
              <img src="@/assets/images/mine.png" alt="" />
            </div>
          </div>
          <div
            v-if="item.person == 'ai'"
            class="all"
            style="margin-bottom: 10px"
          >
            <div class="icon">
              <img src="@/assets/images/talk.png" alt="" />
            </div>
            <div class="aitalk" v-html="item.say"></div>
          </div>
        </div>
      </div>
      <div class="talkInput">
        <!-- <div class="img-list">
          <img
            v-if="imgUrl"
            style="width: 50px; height: 50px"
            :src="imgUrl"
            alt=""
          />
        </div> -->
        <div class="select">
          <span>信号专业知识库</span>
          <!-- <el-select
            :value="kb_name"
            filterable
            placeholder="请选择知识库"
            style="width: 150px; border: none"
            disabled
          >
            <el-option
              key="1be049f5183647b081c7ea6dd21948b2"
              label="信号专业知识库"
              value="1be049f5183647b081c7ea6dd21948b2"
            >
            </el-option>
          </el-select> -->
        </div>
        <form @submit.prevent="getQuestion" class="userSearch">
          <div class="content">
            <div class="upload">
              <el-upload
                action="#"
                :limit="1"
                :file-list="fileList"
                :on-change="handleChange"
                :auto-upload="false"
                list-type="picture"
                accept=".jpg,.png"
                @keydown.enter.native="getQuestion"
              >
                <!-- <i
                  class="el-icon-picture"
                  style="font-size: 30px; color: #28c76c"
                ></i> -->
                <el-button size="small" style="padding: 0">
                  <i
                    class="el-icon-picture"
                    style="font-size: 30px; color: #28c76c"
                  ></i>
                </el-button>
              </el-upload>
            </div>
            <div class="input">
              <el-input
                v-model="contentVal"
                type="textarea"
                placeholder="请输入内容"
                style="resize: none"
                autosize
                :row="2"
                :maxlength="200"
                @keydown.enter.native="getQuestion"
                :disabled="isDisabled"
              ></el-input>
              <!-- isDisabled -->
            </div>
          </div>
        </form>
        <div class="send">
          <i
            class="el-icon-s-promotion"
            style="font-size: 30px; color: #28c76c; margin-right: 20px"
            @click="getQuestion"
          ></i>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
import * as zskApi from "@/api/zsk";
import { marked } from "marked";

export default {
  data() {
    return {
      talkList: [],
      contentVal: "",
      dataList: [],
      kb_name: "1be049f5183647b081c7ea6dd21948b2",
      loading: true,
      isSend: false,
      fileList: [],
      file: "",
      imgUrl: "",
      contentVal_say: "",
      aitalk: "",
      text: "",
      timer: null,
      isDisabled: false,
    };
  },

  created() {
    this.getShow();
    this.getList();
  },

  updated() {
    this.scrollToBottom();
  },

  methods: {
    scrollToBottom() {
      this.$nextTick(() => {
        this.$refs.chatContent.scrollTop = this.$refs.chatContent.scrollHeight;
      });
    },
    selectItem(item) {
      this.kb_name = item.key;
    },
    getList() {
      zskApi
        .select("http://103.177.28.196:7865/v1/knowledge-base/select")
        .then((res) => {
          if (res.code == 1) {
            this.dataList = res.data;
          }
        });
    },
    async getShow() {
      let text = `
        <h1>🚄 你好，我是你的信号专业多模态大模型助手—POC测试</h1>
        <p>👋 我由商汤科技打造，接入了最新的知识库及多模态大模型，能够为你提供专业的工程领域知识参考，是你的工作好帮手～</p>
        <p>你可以在提问框旁选择对应的知识库，让我帮你准确地查询有关的专业知识。</p>
        <p>我有以下一些功能：</p>
        <p>🔍 基于特定的专业知识库，帮你检索对应的法规规范</p>
        <p>👀 上传专业图片，帮你解释图片内容</p>
        <p>❎ 在POC测试阶段，如果你问的问题和专业无关，我会拒绝你哦！</p>
        <br>
        <p>你可以尝试这样来问我：</p>
        <p>- 临时限速服务器（TSRS）与下列哪些系统接口？</p>
        <p>- 调度集中系统(CTC)具备哪两种作业办理模式？</p>
        <p>- 自动闭塞区间信号设备管辖分界要满足哪些要求？</p>
        
        `;
      let m = "";

      for (let i = 0; i < text.length; i++) {
        m += text.charAt(i);
        await new Promise((resolve) => {
          setTimeout(resolve, 30);
        });
        this.aitalk = m;
      }
    },

    handleChange(file, fileList) {
      this.file = file.raw;
      this.fileList = fileList;
      this.imgUrl = file.url;
    },
    changeZSK(val) {
      this.kb_name = val;
    },
    getQuestion(event) {
      if (event.key === "Enter") {
        event.preventDefault();
      }
      if (this.fileList && this.fileList.length > 0) {
        if (this.contentVal) {
          this.talkList.push(
            {
              id: this.generateUniqueID(),
              person: "mine",
              img: this.imgUrl,
            },
            {
              id: this.generateUniqueID(),
              person: "mine",
              say: this.contentVal,
            }
          );
        } else {
          this.talkList.push({
            id: this.generateUniqueID(),
            person: "mine",
            img: this.imgUrl,
          });
        }
        this.isDisabled = true;
        this.getAnswer1();
        this.contentVal = "";
        this.fileList = [];
      } else {
        if (this.contentVal === "") {
          this.$message({
            type: "warning",
            message: "请输入问题",
          });
        } else {
          this.talkList.push({
            id: this.generateUniqueID(),
            person: "mine",
            say: this.contentVal,
          });
          this.isDisabled = true;
          this.getAnswer();
          this.contentVal = "";
        }
      }
    },

    async getAnswer() {
      let isUpdate = true;
      this.talkList.push({
        id: this.generateUniqueID(),
        person: "ai",
        say: "让我想一想",
      });
      let lastObj = this.talkList[this.talkList.length - 1];
      this.timer = setInterval(() => {
        if (isUpdate) {
          if (lastObj.say.length >= 5) {
            lastObj.say += " .";
          }
          if (lastObj.say.length > 11) {
            lastObj.say = "让我想一想";
          }
        }
      }, 200);

      let url = "http://103.177.28.196:7865/chat/knowledge_base_chat";
      let response = await fetch(url, {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
        },
        body: JSON.stringify({
          query: this.contentVal,
          session_id: "session_id",
          kb_name: this.kb_name,
          stream: true,
        }),
      })
        .then()
        .catch((error) => console.error("Fetch error:", error));
      const reader = response.body.getReader();
      const textDecoder = new TextDecoder();

      let answerClear = false;
let index=0
// let list=
      while (true) {
        const { done, value } = await reader.read();
      let chunkText = textDecoder.decode(value);
        if (done) {
          this.isDisabled = false;
          index=0
        console.log("已经获取到所有的流数据");
          break;
        }
        index++
        console.log("第"+index+"次流数据获取：");
        console.log([chunkText]);
        isUpdate = true;
        isUpdate = false;
        this.timer = null;

        if (!isUpdate && !answerClear) {
          answerClear = true;
          lastObj.say = "";
        }

        this.answer = "";

        if (chunkText.lastIndexOf(",") == chunkText.length - 1) {
          chunkText = "[" + chunkText.substring(0, chunkText.length - 1) + "]";
        } else {
          chunkText = "[" + chunkText + "]";
        }
        chunkText = JSON.parse(chunkText);

        for (let item of chunkText) {
          if (item.image_path) {
            let image = item.image_path;

            let iamgePath = image
              .replace("![Image_path](", "")
              .replace(")\n", "");
            console.log(iamgePath);

            let img = `<img style='display:block' src="http://103.177.28.196:7865/knowledge_base/download_image?kb_name=${this.kb_name}&file_hash=${iamgePath}"/>`;
            lastObj.say += img;
            await new Promise((resolve) => {
              setTimeout(resolve, 10);
            });
          } else {
            for (let i = 0; i < item.answer.length; i++) {
              lastObj.say += item.answer.charAt(i);
              lastObj.say = lastObj.say
                .replace("\n", "<br/>")
                .replace("**", "<b>");

              let regex = /<b>/g;
              let matches1 = lastObj.say.match(regex);

              let regex2 = /<\/b>/g;
              let matches2 = lastObj.say.match(regex2);
              await new Promise((resolve) => {
              setTimeout(resolve, 10);
            });
              //处理第一对
              if (
                (matches1 && matches1.length % 2 === 0 && matches2 == null) ||
                (matches1 && matches2 && matches1.length == matches2.length + 2)
              ) {
                lastObj.say =
                  lastObj.say.substring(0, lastObj.say.length - 3) + "</b>";
              }
            }
          }

          await new Promise((resolve) => {
            setTimeout(resolve, 10);
          });
        }
      }
    },
    //多模态
    async getAnswer1() {
      let isUpdate = true;
      this.talkList.push({
        id: this.generateUniqueID(),
        person: "ai",
        say: "让我想一想",
      });
      let lastObj = this.talkList[this.talkList.length - 1];
      //处理。。。
      this.timer = setInterval(() => {
        if (isUpdate) {
          if (lastObj.say.length >= 5) {
            lastObj.say += " .";
          }
          if (lastObj.say.length > 11) {
            lastObj.say = "让我想一想";
          }
        }
      }, 200);
      //获取数据
      // await this.$http
      //   .post(
      //     "http://103.177.28.196:7865/chat/multimodal_chat",
      //     {
      //       file: this.file,
      //       query: this.contentVal,
      //       kb_name: this.kb_name,
      //       stream: true,
      //     },
      //     {
      //       headers: {
      //         "Content-Type": "multipart/form-data",
      //         "response-type": "stream",
      //       },

      //     }
      //   )
      //   .then(async (res) => {
      //     console.log(res);
      //     if (res.status == 200) {
      //       console.log(res.data);
      //       //   let result = res.data[0].result;
      //       //   isUpdate = false;
      //       //   lastObj.say = "";
      //       //   for (let i = 0; i < result.length; i++) {
      //       //     lastObj.say += result.charAt(i);
      //       //     await new Promise((resolve) => {
      //       //       setTimeout(resolve, 50);
      //       //     });
      //       //   }
      //     }
      //   });
      const formData = new FormData();
      formData.append('file', this.file);
      formData.append('query', this.contentVal);
      formData.append('kb_name', this.kb_name);
      formData.append('stream', true);
      let response = await fetch("http://103.177.28.196:7865/chat/multimodal_chat", {
        method: "POST",
        body:formData 
      })
        .then()
        .catch((error) => console.error("Fetch error:", error));
      const reader = response.body.getReader();
      const textDecoder = new TextDecoder();

      let answerClear = false;

      while (true) {
        const { done, value } = await reader.read();
        if (done) {
          this.isDisabled = false;
          break;
        }
        isUpdate = true;
        isUpdate = false;
        this.timer = null;

        if (!isUpdate && !answerClear) {
          answerClear = true;
          lastObj.say = "";
        }

        this.answer = "";
        let chunkText = textDecoder.decode(value);
        if (chunkText.lastIndexOf(",") == chunkText.length - 1) {
          chunkText = "[" + chunkText.substring(0, chunkText.length - 1) + "]";
        } else {
          chunkText = "[" + chunkText + "]";
        }
        chunkText = JSON.parse(chunkText);

        for (let item of chunkText) {
          if (item.image_path) {
            let image = item.image_path;

            let iamgePath = image
              .replace("![Image_path](", "")
              .replace(")\n", "");
            console.log(iamgePath);

            let img = `<img style='display:block' src="http://103.177.28.196:7865/knowledge_base/download_image?kb_name=${this.kb_name}&file_hash=${iamgePath}"/>`;
            lastObj.say += img;
            await new Promise((resolve) => {
              setTimeout(resolve, 30);
            });
          } else {
            for (let i = 0; i < item.answer.length; i++) {
              lastObj.say += item.answer.charAt(i);
              lastObj.say = lastObj.say
                .replace("\n", "<br/>")
                .replace("**", "<b>");

              let regex = /<b>/g;
              let matches1 = lastObj.say.match(regex);

              let regex2 = /<\/b>/g;
              let matches2 = lastObj.say.match(regex2);

              //处理第一对
              if (
                (matches1 && matches1.length % 2 === 0 && matches2 == null) ||
                (matches1 && matches2 && matches1.length == matches2.length + 2)
              ) {
                lastObj.say =
                  lastObj.say.substring(0, lastObj.say.length - 3) + "</b>";
              }
            }
          }

          await new Promise((resolve) => {
            setTimeout(resolve, 30);
          });
        }
      }
        

    },

    //生成id

    generateUniqueID() {
      // 使用当前日期和时间以及随机数生成唯一ID
      const time = new Date().getTime();
      const random = Math.random().toString(36).substring(2, 15);
      return "id_" + time + "_" + random;
    },
  },
};
</script>

<style scoped>
.talkContainer {
  width: 80%;
  margin: 10px auto;
  display: flex;
  flex-direction: column;
  height: 100%;
}

.talkContent {
  width: 100%;
  flex: 1;
  overflow: auto;
}

.talkContent::-webkit-scrollbar {
  display: none; /* 针对Webkit浏览器隐藏滚动条 */
}
.talkInput {
  width: 100%;
  margin-bottom: 30px;
  background-color: #fff;
  border-radius: 15px;
  display: flex;
  justify-content: center;
  align-items: center;
  position: relative;
}

.img-list {
  display: flex;
  align-items: center;
  justify-content: start;
}

.all {
  display: flex;
  justify-content: start;
  align-items: center;
}

.icon img {
  width: 20px;
  height: 20px;
}

.aitalk {
  /* width: 50%; */
  margin-left: 10px;
  padding: 8px 10px 12px;
  background-color: #fff;
  border-radius: 15px;
}
.userSearch {
  display: flex;
  flex: 1;
}
.content {
  width: 100%;
  display: flex;
  justify-content: start;
  align-items: center;
}

.el-textarea /deep/ .el-textarea__inner {
  resize: none;
  border: none;
  height: 70px !important;
  max-height: 70px;
  /* line-height: 70px; */
  /* border: 1px solid red; */
}
.input {
  flex: 1;
  display: flex;
  align-items: center;
}
.el-textarea {
  /* border: 1px solid red; */
  display: flex;
  align-items: center;
  font-size: 20px !important;
  font-weight: 600;
  /* height: 70px !important; */
  /* line-height: 70px; */
}
.select,
.send,
.upload {
  margin: 0 10px;
}

.mine {
  display: flex;
  justify-content: end;
  align-items: center;
  padding: 15px 0;
  margin: 20px 0;
}
.ai {
  display: flex;
  justify-content: start;
  align-items: center;
  background-color: #fff;
  padding: 15px 0;
}

.question {
  margin-right: 10px;
  font-weight: 600;
}
.upload div {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin: 0 10px;
}
.upload /deep/ .el-upload-list__item-name {
  display: none;
}
.upload /deep/.el-upload-list__item-thumbnail {
  width: 50px;
  height: 50px;
  position: absolute;
  margin-left: 0px;
}
.upload /deep/ .el-upload-list__item {
  width: 80px;
  height: 80px;
  padding: 15px 0 0 13px;
}

.upload /deep/ .el-icon-close {
  right: 0;
}
</style>